package chagine.core.lock.redis.util;

import chagine.core.lock.util.PlatformUtils;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.EqualsAndHashCode;

/**
 * 锁信息
 *
 * @author lixiaohui
 * @date 2016年9月14日 上午10:22:39
 */
@EqualsAndHashCode
public class LockInfo {

    private long expires;

    private String mac;

    private long jvmPid;

    private long threadId;

    private int count;

    @JsonIgnore
    private static final transient String LOCAL_MAC = PlatformUtils.MACAddress();

    @JsonIgnore
    private static final transient int CURRENT_PID = PlatformUtils.JVMPid();

    public LockInfo incCount() {
        if (count == Integer.MAX_VALUE) {
            throw new Error("Maximum lock count exceeded");
        }
        ++count;
        return this;
    }

    public LockInfo decCount() {
        --count;
        return this;
    }

    @JsonIgnore
    public boolean isCurrentThread() {
        return mac.equals(LOCAL_MAC) && jvmPid == CURRENT_PID && Thread.currentThread().getId() == threadId;
    }

    public static LockInfo newForCurrThread(long expires) {
        LockInfo lockInfo = new LockInfo();
        lockInfo.setThreadId(Thread.currentThread().getId());
        lockInfo.setCount(1);
        lockInfo.setExpires(expires);
        lockInfo.setJvmPid(CURRENT_PID);
        lockInfo.setMac(LOCAL_MAC);
        return lockInfo;
    }

    public long getExpires() {
        return expires;
    }

    public LockInfo setExpires(long expires) {
        this.expires = expires;
        return this;
    }

    public String getMac() {
        return mac;
    }

    public LockInfo setMac(String mac) {
        this.mac = mac;
        return this;
    }

    public long getJvmPid() {
        return jvmPid;
    }

    public LockInfo setJvmPid(long jvmPid) {
        this.jvmPid = jvmPid;
        return this;
    }

    public long getThreadId() {
        return threadId;
    }

    public LockInfo setThreadId(long threadId) {
        this.threadId = threadId;
        return this;
    }

    public int getCount() {
        return count;
    }

    public LockInfo setCount(int count) {
        this.count = count;
        return this;
    }

    public boolean isSame(Object obj) {
        if (obj == null) {
            return false;
        }
        LockInfo info = (LockInfo) obj;
        return info.getMac().equals(mac)
                && info.getJvmPid() == jvmPid
                && info.getThreadId() == threadId
                && info.getExpires() == expires
                && info.getCount() == count;
    }

    public String toSimpleString() {
        return "expires:" + expires +
                ",mac:" + mac +
                ",jvmPid:" + jvmPid +
                ",threadId:" + threadId +
                ",count:" + count;
    }
}
